/*
 * 文件名：config.cpp
 * 功能描述：系统配置管理和参数存储
 */

#include "config.h"
#include "bsp_motor.h"
#include <nvs.h>
#include <nvs_flash.h>

/// E01-PW-e2   棋子丢失，检查棋子,重新摆好即可
/// E02         电量低，请充电
/// E03         ID板断线

int batteryLevel_g = 0;
int beepLevel_g = 10;
int speed_g = 3000;
bool speaker_g = true;
int errorCode = 200;
//在event.cpp中定义，其余地方只声明他的存在
extern int encoderValue;
bool encoderButton = false;
bool id_status = false;
bool calibration_x_g = false;
bool calibration_y_g = false;
String firmware_name_g = "Chessbot";
String firmware_version_g = "v1.0.0";
bool firmware_status = false;
int level_difficulty_g = 1; // 难度等级
bool button_state = 1;
bool button_state2 = 1;
bool wifi_status_g = false;
bool deviceConnected_g = false;
bool firmware_new_status = false;
bool isSyncing = false;
bool serial_enable_g = true; // 默认启用串口
int mode_g = 1;
bool Charging_status = false;
int print_key = 0;
String sn_g = "XZ000000000";
String ip_g = "";
String wifi_name_g = "";
// 保存最后移动坐标
float last_x_g = 0;
float last_y_g = 0;
int get_current_speed()
{
    int speed = 0;
    if (speed_g == 7000)
    {
        speed = 3;
    }
    else if (speed_g == 5000)
    {
        speed = 2;
    }
    else if (speed_g == 3000)
    {
        speed = 1;
    }
    return speed;
}

void beep_set(int level)
{
    beepLevel_g = level;
    savePreferences();
    if (print_key)
    {
        Serial.printf("蜂鸣器音量为：%d", beepLevel_g);
    }
}

void motor_speed_set(String speed)
{
    if (speed == "high")
    {
        if (print_key)
        {
            Serial.println("设置速度为高！");
        }
        speed_g = 7000;
    }
    else if (speed == "mid")
    {
        if (print_key)
        {
            Serial.println("设置速度为中！");
        }
        speed_g = 5000;
    }
    else if (speed == "low")
    {
        if (print_key)
        {
            Serial.println("设置速度为低！");
        }
        speed_g = 3000;
    }
    Xaxis.setMaxSpeed(speed_g);
    Yaxis.setMaxSpeed(speed_g);
    Xaxis.setAcceleration(speed_g * 0.8);
    Yaxis.setAcceleration(speed_g * 0.8);
}

void speed_set(int speed)
{
    if (speed == 3)
    {
        if (print_key)
        {
            Serial.println("设置速度为超高！");
        }
        speed_g = 7000;
    }
    else if (speed == 2)
    {
        if (print_key)
        {
            Serial.println("设置速度为高！");
        }
        speed_g = 5000;
    }
    else if (speed == 1)
    {
        if (print_key)
        {
            Serial.println("设置速度为中！");
        }
        speed_g = 3000;
    }
    Xaxis.setMaxSpeed(speed_g);
    Yaxis.setMaxSpeed(speed_g);
    Xaxis.setAcceleration(speed_g * 0.8);
    Yaxis.setAcceleration(speed_g * 0.8);
}

void speaker_set(String value)
{
    if (value == "on")
    {
        if (print_key)
        {
            Serial.println("打开语音模块！");
        }
        speaker_g = true;
        // 使用新的更新状态函数
        // updateVoiceStatus(true);
        sendFrameToVoiceModule(0x03);
    }
    else if (value == "off")
    {
        if (print_key)
        {
            Serial.println("关闭语音模块！");
        }
        sendFrameToVoiceModule(0x04);
        speaker_g = false;
        // 使用新的更新状态函数
        // updateVoiceStatus(false);
    }
}
void savelocation(float x, float y)
{
    esp_err_t err = nvs_flash_init();
    if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND)
    {
        nvs_flash_erase();      // 清除NVS存储
        err = nvs_flash_init(); // 重新初始化
    }

    if (err != ESP_OK)
    {
        if (print_key)
        {
            Serial.println("Failed to initialize NVS");
        }
        return;
    }

    nvs_handle my_handle;
    err = nvs_open("settings", NVS_READWRITE, &my_handle); // 打开NVS存储空间
    if (err != ESP_OK)
    {
        // Serial.println("Failed to open NVS handle");
        return;
    }

    // 保存X坐标
    err = nvs_set_i32(my_handle, NVS_KEY_LAST_X, (int32_t)(x));
    if (err != ESP_OK)
    {
        if (print_key)
        {
            Serial.println("Failed to write last_x");
        }
    }

    // 保存Y坐标
    err = nvs_set_i32(my_handle, NVS_KEY_LAST_Y, (int32_t)(y));
    if (err != ESP_OK)
    {
        if (print_key)
        {
            Serial.println("Failed to write last_y");
        }
    }

    // 提交NVS更改到存储
    err = nvs_commit(my_handle);
    if (err != ESP_OK)
    {
        if (print_key)
        {
            Serial.println("Failed to commit changes to NVS");
        }
    }

    // 关闭NVS句柄
    nvs_close(my_handle);

    // 同时更新全局变量
    last_x_g = x;
    last_y_g = y;

    if (print_key)
    {
        Serial.printf("已保存机芯位置: x=%f, y=%f\n", x, y);
    }
}

/**
 * @brief 保存系统偏好设置到NVS存储
 * @details 保存内容包括：
 * - 固件名称和版本
 * - 声音相关设置
 * - 运动参数
 * - 系统模式配置
 * @warning 需要先初始化NVS存储空间
 */
// 保存偏好设置到NVS存储
void savePreferences()
{
    // 初始化NVS
    esp_err_t err = nvs_flash_init();
    if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND)
    {
        nvs_flash_erase();      // 清除NVS存储
        err = nvs_flash_init(); // 重新初始化
    }

    if (err != ESP_OK)
    {
        if (print_key)
        {
            Serial.println("Failed to initialize NVS");
        }
        return;
    }

    nvs_handle my_handle;
    err = nvs_open("settings", NVS_READWRITE, &my_handle); // 打开NVS存储空间
    if (err != ESP_OK)
    {
        // Serial.println("Failed to open NVS handle");
        return;
    }

    // 使用 c_str() 方法将 String 转换为 const char* 类型
    //设置 "firmware_name"的值
    err = nvs_set_str(my_handle, "firmware_name", firmware_name_g.c_str());
    if (err != ESP_OK)
    {
        // Serial.println("Failed to write firmware_name");
    }
    err = nvs_set_str(my_handle, "firmware_v", firmware_version_g.c_str());
    if (err != ESP_OK)
    {
        // Serial.println("Failed to write firmware_v");
    }
    err = nvs_set_str(my_handle, "beepLevel", String(beepLevel_g).c_str());
    if (err != ESP_OK)
    {
        // Serial.println("Failed to write beepLevel");
    }
    err = nvs_set_str(my_handle, "speed", String(get_current_speed()).c_str());
    if (err != ESP_OK)
    {
        // Serial.println("Failed to write speed");
    }
    err = nvs_set_str(my_handle, "speaker", String(speaker_g).c_str());
    if (err != ESP_OK)
    {
        // Serial.println("Failed to write speaker");
    }
    err = nvs_set_str(my_handle, "level", String(level_difficulty_g).c_str());
    if (err != ESP_OK)
    {
        // Serial.println("Failed to write level");
    }
    err = nvs_set_str(my_handle, "mode", String(mode_g).c_str());
    if (err != ESP_OK)
    {
        // Serial.println("Failed to write mode_g");
    }
    // 写入数据
    err = nvs_set_str(my_handle, "s_n_g", sn_g.c_str());
    if (err != ESP_OK)
    {
        // Serial.print("Failed to write sn, error code: ");
    }
    // 提交写入的数据
    err = nvs_commit(my_handle);
    if (err != ESP_OK)
    {
        // Serial.println("Failed to commit changes to NVS");
    }

    // 关闭NVS存储
    nvs_close(my_handle);
    //
    //    logManager.writeFormattedLog("保存偏好设置：\n"
    //                                 "固件名称: %s\n"
    //                                 "固件版本: %s\n"
    //                                 "音量: %d\n"
    //                                 "速度: %d\n"
    //                                 "开关状态: %d\n"
    //                                 "难度: %d\n"
    //                                 "模式: %d",
    //                                 firmware_name_g.c_str(), firmware_version_g.c_str(), beepLevel_g, get_current_speed(), speaker_g, level_difficulty_g, mode_g);
}
void save_level()
{
    // 初始化NVS,使用前要初始化
    esp_err_t err = nvs_flash_init();
    if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND)
    {
        nvs_flash_erase();      // 清除NVS存储
        err = nvs_flash_init(); // 重新初始化
    }

    if (err != ESP_OK)
    {
        if (print_key)
        {
            Serial.println("Failed to initialize NVS");
        }
        return;
    }

    nvs_handle my_handle;
    err = nvs_open("settings", NVS_READWRITE, &my_handle); // 打开NVS存储空间
    if (err != ESP_OK)
    {
        // Serial.println("Failed to open NVS handle");
        return;
    }

    err = nvs_set_str(my_handle, "level", String(level_difficulty_g).c_str());
    if (err != ESP_OK)
    {
        // Serial.println("Failed to write level");
    }
    // 提交写入的数据
    err = nvs_commit(my_handle);
    if (err != ESP_OK)
    {
        // Serial.println("Failed to commit changes to NVS");
    }
    // 关闭NVS存储
    nvs_close(my_handle);
}
/**
 * @brief NVS字符串读取辅助函数
 * @param my_handle NVS操作句柄
 * @param key 要读取的键名
 * @return String 读取到的字符串值，读取失败返回空字符串
 * @note 该函数会自动管理内存分配，调用者无需手动释放
 */
String readStringFromNVS(nvs_handle my_handle, const char *key)
{
    size_t required_size;
    //一般会传入一个地址来接收nvs里面对应的值
    //这里传入 NULL 是一个​​特殊操作​​。它告诉函数：
    //“我现在不关心字符串的内容是什么，我只想知道存储这个字符串需要多大的内存空间,存入required_size
    esp_err_t err = nvs_get_str(my_handle, key, NULL, &required_size);
    if (err != ESP_OK)
    {
        // Serial.println("Failed to read " + String(key));
        return ""; // 如果读取失败，返回空字符串
    }

    char *str = (char *)malloc(required_size);
    if (str == NULL)
    {
        // Serial.println("Failed to allocate memory for " + String(key));
        return ""; // 如果分配内存失败，返回空字符串
    }
    //将nvs里面的键值对读取放str入这个地址空间
    err = nvs_get_str(my_handle, key, str, &required_size);
    String result = (err == ESP_OK) ? String(str) : ""; // 读取成功则返回字符串，否则返回空字符串
    free(str);                                          // 释放内存
    return result;
}

/**
 * @brief 从NVS加载系统偏好设置
 * @note 如果检测到NVS版本更新，会自动擦除并重建存储分区
 * @warning 内存分配失败时会返回空字符串
 */
void loadPreferences()
{   //使用前要初始化分区，准备硬件和软件
    esp_err_t err = nvs_flash_init();
    if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND)
    {
        nvs_flash_erase();      // 清除NVS存储
        err = nvs_flash_init(); // 重新初始化
    }

    if (err != ESP_OK)
    {
        // Serial.println("Failed to initialize NVS");
        return;
    }

    nvs_handle my_handle;
    err = nvs_open("settings", NVS_READONLY, &my_handle); // 打开NVS存储空间
    if (err != ESP_OK)
    {
        // Serial.println("Failed to open NVS handle");
        return;
    }

    // 获取各个偏好设置
    firmware_name_g = readStringFromNVS(my_handle, "firmware_name");
    firmware_version_g = readStringFromNVS(my_handle, "firmware_v");
    beepLevel_g = readStringFromNVS(my_handle, "beepLevel").toInt();
    speed_set(readStringFromNVS(my_handle, "speed").toInt());
    speaker_g = readStringFromNVS(my_handle, "speaker").toInt();
    level_difficulty_g = readStringFromNVS(my_handle, "level").toInt();
    mode_g = readStringFromNVS(my_handle, "mode").toInt();
    sn_g = readStringFromNVS(my_handle, "s_n_g");
    // 新增：读取机芯位置
    int32_t x = 0, y = 0;
    nvs_get_i32(my_handle, NVS_KEY_LAST_X, &x);
    nvs_get_i32(my_handle, NVS_KEY_LAST_Y, &y);
    last_x_g = float(x);
    last_y_g = float(y);
    if (print_key)
    {
        Serial.printf("last_x_g: %f, last_y_g: %f\n", last_x_g, last_y_g);
    }
    // 关闭NVS存储
    nvs_close(my_handle);
}
